/*
 * sm2-1.0.js
 */
/**
 * @name sm2-1.0.js
 * @version 1.0.0
 */

var debug = false;
//国密推荐曲线
var sm2_ecParams = {
	"p": "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF",
	"a": "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC",
	"b": "28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93",
	"n": "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123",
	"gx": "32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7",
	"gy": "BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0",
	"keylen": 256
};
function myBrowser() {
	var D = navigator.userAgent;
	var F = D.indexOf("Opera") > -1;
	var B = D.indexOf("compatible") > -1 && D.indexOf("MSIE") > -1;
	var E = D.indexOf("Edge") > -1 && !B;
	var C = D.indexOf("Trident") > -1 && D.indexOf("rv:11.0") > -1;
	var H = D.indexOf("Firefox") > -1;
	var A = D.indexOf("Safari") > -1;
	var G = D.indexOf("Chrome") > -1;
	if (E) {
			return "edge"
	}
	if (C) {
			return "IE11"
	}
	if (H) {
			return "FF"
	}
	if (G) {
			return "FF"
	}
}
function SM3Digest2() {
	this.BYTE_LENGTH = 64;
	this.xBuf = [];
	this.xBufOff = 0;
	this.byteCount = 0;
	this.DIGEST_LENGTH = 32;
	this.v0 = [1937774191, 1226093241, 388252375, -628488704, -1452330820, 372324522, -477237683, -1325724082];
	this.v = [0, 0, 0, 0, 0, 0, 0, 0];
	this.v_ = [0, 0, 0, 0, 0, 0, 0, 0];
	this.X0 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
	this.X = [68];
	this.xOff = 0;
	this.T_00_15 = 2043430169;
	this.T_16_63 = 2055708042;
	if (arguments.length > 0) {
			this.InitDigest(arguments[0])
	} else {
			this.Init()
	}
}
SM3Digest2.prototype = {
	Init: function() {
			this.xBuf = [0, 0, 0, 0];
			this.Reset()
	},
	InitDigest: function(A) {
			this.xBuf = [A.xBuf.length];
			Array.Copy(A.xBuf, 0, this.xBuf, 0, A.xBuf.length);
			this.xBufOff = A.xBufOff;
			this.byteCount = A.byteCount;
			Array.Copy(A.X, 0, this.X, 0, A.X.length);
			this.xOff = A.xOff;
			Array.Copy(A.v, 0, this.v, 0, A.v.length)
	},
	GetDigestSize: function() {
			return this.DIGEST_LENGTH
	},
	Reset: function() {
			this.byteCount = 0;
			this.xBufOff = 0;
			Array.Clear(this.xBuf, 0, this.xBuf.length);
			Array.Copy(this.v0, 0, this.v, 0, this.v0.length);
			this.xOff = 0;
			Array.Copy(this.X0, 0, this.X, 0, this.X0.length)
	},
	ProcessBlock: function() {
			var H;
			var E = this.X;
			var A = [64];
			for (H = 16; H < 68; H += 1) {
					E[H] = this.P1(E[H - 16] ^ E[H - 9] ^ (roateLeft(E[H - 3], 15))) ^ (roateLeft(E[H - 13], 7)) ^ E[H - 6]
			}
			for (H = 0; H < 64; H += 1) {
					A[H] = E[H] ^ E[H + 4]
			}
			var F = this.v;
			var J = this.v_;
			Array.Copy(F, 0, J, 0, this.v0.length);
			var B, C, G, I, D;
			for (H = 0; H < 16; H += 1) {
					D = roateLeft(J[0], 12);
					B = D + J[4] + roateLeft(this.T_00_15, H);
					B = roateLeft(B, 7);
					C = B ^ D;
					G = this.FF_00_15(J[0], J[1], J[2]) + J[3] + C + A[H];
					I = this.GG_00_15(J[4], J[5], J[6]) + J[7] + B + E[H];
					J[3] = J[2];
					J[2] = roateLeft(J[1], 9);
					J[1] = J[0];
					J[0] = G;
					J[7] = J[6];
					J[6] = roateLeft(J[5], 19);
					J[5] = J[4];
					J[4] = this.P0(I)
			}
			for (H = 16; H < 64; H += 1) {
					D = roateLeft(J[0], 12);
					B = D + J[4] + roateLeft(this.T_16_63, H);
					B = roateLeft(B, 7);
					C = B ^ D;
					G = this.FF_16_63(J[0], J[1], J[2]) + J[3] + C + A[H];
					I = this.GG_16_63(J[4], J[5], J[6]) + J[7] + B + E[H];
					J[3] = J[2];
					J[2] = roateLeft(J[1], 9);
					J[1] = J[0];
					J[0] = G;
					J[7] = J[6];
					J[6] = roateLeft(J[5], 19);
					J[5] = J[4];
					J[4] = this.P0(I)
			}
			for (H = 0; H < 8; H += 1) {
					F[H] ^= (J[H])
			}
			this.xOff = 0;
			Array.Copy(this.X0, 0, this.X, 0, this.X0.length)
	},
	ProcessWord: function(B, A) {
			var C = B[A] << 24;
			C |= (B[A += 1] & 255) << 16;
			C |= (B[A += 1] & 255) << 8;
			C |= (B[A += 1] & 255);
			this.X[this.xOff] = C;
			if (++this.xOff == 16) {
					this.ProcessBlock()
			}
	},
	ProcessLength: function(A) {
			if (this.xOff > 14) {
					this.ProcessBlock()
			}
			this.X[14] = (this.URShiftLong(A, 32));
			this.X[15] = (A & (4294967295))
	},
	IntToBigEndian: function(B, C, A) {
			C[A] = (B >>> 24 & 255);
			C[A += 1] = (B >>> 16 & 255);
			C[A += 1] = (B >>> 8 & 255);
			C[A += 1] = (B & 255)
	},
	DoFinal: function(C, A) {
			this.Finish();
			for (var B = 0; B < 8; B += 1) {
					this.IntToBigEndian(this.v[B], C, A + B * 4)
			}
			this.Reset();
			return this.DIGEST_LENGTH
	},
	Update: function(A) {
			this.xBuf[this.xBufOff++] = A;
			if (this.xBufOff == this.xBuf.length) {
					this.ProcessWord(this.xBuf, 0);
					this.xBufOff = 0
			}
			this.byteCount++
	},
	BlockUpdate: function(C, A, B) {
			while ((this.xBufOff != 0) && (B > 0)) {
					this.Update(C[A]);
					A += 1;
					B -= 1
			}
			while (B > this.xBuf.length) {
					this.ProcessWord(C, A);
					A += this.xBuf.length;
					B -= this.xBuf.length;
					this.byteCount += this.xBuf.length
			}
			while (B > 0) {
					this.Update(C[A]);
					A += 1;
					B -= 1
			}
	},
	Finish: function() {
			var A = (this.byteCount << 3);
			this.Update((128));
			while (this.xBufOff != 0) {
					this.Update((0))
			}
			this.ProcessLength(A);
			this.ProcessBlock()
	},
	ROTATE: function(B, A) {
			return (B << A) | (this.URShift(B, (32 - A)))
	},
	P0: function(A) {
			return ((A) ^ roateLeft((A), 9) ^ roateLeft((A), 17))
	},
	P1: function(A) {
			return ((A) ^ roateLeft((A), 15) ^ roateLeft((A), 23))
	},
	FF_00_15: function(B, C, A) {
			return (B ^ C ^ A)
	},
	FF_16_63: function(B, C, A) {
			return ((B & C) | (B & A) | (C & A))
	},
	GG_00_15: function(B, C, A) {
			return (B ^ C ^ A)
	},
	GG_16_63: function(B, C, A) {
			return ((B & C) | (~B & A))
	},
	URShift: function(B, A) {
			console.error(B);
			if (B > Int32.maxValue || B < Int32.minValue) {
					console.error(B);
					B = IntegerParse(B)
			}
			if (B >= 0) {
					return B >> A
			} else {
					return (B >> A) + (2 << ~A)
			}
	},
	URShiftLong: function(A, C) {
			var J;
			var B = new BigInteger();
			B.fromInt(A);
			if (B.signum() >= 0) {
					J = B.shiftRight(C).intValue()
			} else {
					var E = new BigInteger();
					E.fromInt(2);
					var K = ~C;
					var F = "";
					if (K < 0) {
							var I = 64 + K;
							for (var H = 0; H < I; H += 1) {
									F += "0"
							}
							var G = new BigInteger();
							G.fromInt(A >> C);
							var L = new BigInteger("10" + F, 2);
							F = L.toRadix(10);
							var D = L.add(G);
							J = D.toRadix(10)
					} else {
							F = E.shiftLeft((~C)).intValue();
							J = (A >> C) + F
					}
			}
			return J
	},
	GetZ: function(L, B, F) {
			var M = CryptoJS.enc.Utf8.parse(F);
			var J = M.words.length * 4 * 8;
			this.Update((J >> 8 & 255));
			this.Update((J & 255));
			var G = this.GetWords(M.toString());
			this.BlockUpdate(G, 0, G.length);
			var A = this.GetWords(L.curve.a.toBigInteger().toRadix(16));
			var C = this.GetWords(L.curve.b.toBigInteger().toRadix(16));
			var E = this.GetWords(L.getX().toBigInteger().toRadix(16));
			var D = this.GetWords(L.getY().toBigInteger().toRadix(16));
			var I = this.GetWords(B.substr(0, 64));
			var H = this.GetWords(B.substr(64, 64));
			this.BlockUpdate(A, 0, A.length);
			this.BlockUpdate(C, 0, C.length);
			this.BlockUpdate(E, 0, E.length);
			this.BlockUpdate(D, 0, D.length);
			this.BlockUpdate(I, 0, I.length);
			this.BlockUpdate(H, 0, H.length);
			var K = [this.GetDigestSize()];
			this.DoFinal(K, 0);
			return K
	},
	GetWords: function(C) {
			var A = [];
			var D = C.length;
			for (var B = 0; B < D; B += 2) {
					A[A.length] = parseInt(C.substr(B, 2), 16)
			}
			return A
	},
	GetHex: function(D) {
			var A = [];
			var E = 0;
			for (var B = 0; B < D.length * 2; B += 2) {
					A[B >>> 3] |= parseInt(D[E]) << (24 - (B % 8) * 4);
					E += 1
			}
			var C = new CryptoJS.lib.WordArray.init(A, D.length);
			return C
	}
};
Array.Clear = function(A, C, B) {
	for (elm in A) {
			A[elm] = null
	}
};
Array.Copy = function(C, E, A, D, B) {
	C = C.slice(E, E + B);
	for (E = 0; E < C.length; E++) {
			A[D] = C[E],
			D++
	}
};
function roateLeft(A, B) {
	return (A << B) | (A >>> -B)
}
var KJUR

var CryptoJS = CryptoJS || (function(J, A) {
	var E = {};
	var K = E.lib = {};
	var N = K.Base = (function() {
			function C() {}
			return {
					extend: function(P) {
							C.prototype = this;
							var O = new C();
							if (P) {
									O.mixIn(P)
							}
							if (!O.hasOwnProperty("init")) {
									O.init = function() {
											O.$super.init.apply(this, arguments)
									}
							}
							O.init.prototype = O;
							O.$super = this;
							return O
					},
					create: function() {
							var O = this.extend();
							O.init.apply(O, arguments);
							return O
					},
					init: function() {},
					mixIn: function(P) {
							for (var O in P) {
									if (P.hasOwnProperty(O)) {
											this[O] = P[O]
									}
							}
							if (P.hasOwnProperty("toString")) {
									this.toString = P.toString
							}
					},
					clone: function() {
							return this.init.prototype.extend(this)
					}
			}
	} ());
	var B = K.WordArray = N.extend({
			init: function(C, O) {
					C = this.words = C || [];
					if (O != A) {
							this.sigBytes = O
					} else {
							this.sigBytes = C.length * 4
					}
			},
			toString: function(C) {
					return (C || D).stringify(this)
			},
			concat: function(R) {
					var P = this.words;
					var T = R.words;
					var C = this.sigBytes;
					var S = R.sigBytes;
					this.clamp();
					if (C % 4) {
							for (var O = 0; O < S; O += 1) {
									var Q = (T[O >>> 2] >>> (24 - (O % 4) * 8)) & 255;
									P[(C + O) >>> 2] |= Q << (24 - ((C + O) % 4) * 8)
							}
					} else {
							if (T.length > 65535) {
									for (var O = 0; O < S; O += 4) {
											P[(C + O) >>> 2] = T[O >>> 2]
									}
							} else {
									P.push.apply(P, T)
							}
					}
					this.sigBytes += S;
					return this
			},
			clamp: function() {
					var C = this.words;
					var O = this.sigBytes;
					C[O >>> 2] &= 4294967295 << (32 - (O % 4) * 8);
					C.length = J.ceil(O / 4)
			},
			clone: function() {
					var C = N.clone.call(this);
					C.words = this.words.slice(0);
					return C
			},
			random: function(P) {
					var C = [];
					for (var O = 0; O < P; O += 4) {
							C.push((J.random() * 4294967296) | 0)
					}
					return new B.init(C, P)
			}
	});
	var I = E.enc = {};
	var D = I.Hex = {
			stringify: function(P) {
					var C = P.words;
					var S = P.sigBytes;
					var Q = [];
					for (var O = 0; O < S; O += 1) {
							var R = (C[O >>> 2] >>> (24 - (O % 4) * 8)) & 255;
							Q.push((R >>> 4).toString(16));
							Q.push((R & 15).toString(16))
					}
					return Q.join("")
			},
			parse: function(P) {
					var Q = P.length;
					var C = [];
					for (var O = 0; O < Q; O += 2) {
							C[O >>> 3] |= parseInt(P.substr(O, 2), 16) << (24 - (O % 8) * 4)
					}
					return new B.init(C, Q / 2)
			}
	};
	var M = I.Latin1 = {
			stringify: function(P) {
					var C = P.words;
					var S = P.sigBytes;
					var Q = [];
					for (var O = 0; O < S; O += 1) {
							var R = (C[O >>> 2] >>> (24 - (O % 4) * 8)) & 255;
							Q.push(String.fromCharCode(R))
					}
					return Q.join("")
			},
			parse: function(O) {
					var Q = O.length;
					var C = [];
					for (var P = 0; P < Q; P += 1) {
							C[P >>> 2] |= (O.charCodeAt(P) & 255) << (24 - (P % 4) * 8)
					}
					return new B.init(C, Q)
			}
	};
	var G = I.Utf8 = {
			stringify: function(O) {
					try {
							return decodeURIComponent(escape(M.stringify(O)))
					} catch(C) {
							throw new Error("Malformed UTF-8 data")
					}
			},
			parse: function(C) {
					return M.parse(unescape(encodeURIComponent(C)))
			}
	};
	var L = K.BufferedBlockAlgorithm = N.extend({
			reset: function() {
					this._data = new B.init();
					this._nDataBytes = 0
			},
			_append: function(C) {
					if (typeof C == "string") {
							C = G.parse(C)
					}
					this._data.concat(C);
					this._nDataBytes += C.sigBytes
			},
			_process: function(O) {
					var Q = this._data;
					var C = Q.words;
					var S = Q.sigBytes;
					var R = this.blockSize;
					var V = R * 4;
					var W = S / V;
					if (O) {
							W = J.ceil(W)
					} else {
							W = J.max((W | 0) - this._minBufferSize, 0)
					}
					var U = W * R;
					var T = J.min(U * 4, S);
					if (U) {
							for (var P = 0; P < U; P += R) {
									this._doProcessBlock(C, P)
							}
							var X = C.splice(0, U);
							Q.sigBytes -= T
					}
					return new B.init(X, T)
			},
			clone: function() {
					var C = N.clone.call(this);
					C._data = this._data.clone();
					return C
			},
			_minBufferSize: 0
	});
	var F = K.Hasher = L.extend({
			cfg: N.extend(),
			init: function(C) {
					this.cfg = this.cfg.extend(C);
					this.reset()
			},
			reset: function() {
					L.reset.call(this);
					this._doReset()
			},
			update: function(C) {
					this._append(C);
					this._process();
					return this
			},
			finalize: function(C) {
					if (C) {
							this._append(C)
					}
					var O = this._doFinalize();
					return O
			},
			blockSize: 512 / 32,
			_createHelper: function(C) {
					return function(P, O) {
							return new C.init(O).finalize(P)
					}
			},
			_createHmacHelper: function(C) {
					return function(P, O) {
							return new H.HMAC.init(C, O).finalize(P)
					}
			}
	});
	var H = E.algo = {};
	return E
} (Math));
var lowprimes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997];
var lplim = (1 << 26) / lowprimes[lowprimes.length - 1];
function SM2Cipher(A) {
	this.ct = 1;
	this.p2 = null;
	this.sm3keybase = null;
	this.sm3c3 = null;
	this.key = new Array(32);
	this.keyOff = 0;
	if (typeof(A) != "undefined") {
			this.cipherMode = A
	} else {
			this.cipherMode = SM2CipherMode.C1C3C2
	}
}
SM2Cipher.prototype = {
	Reset: function() {
			this.sm3keybase = new SM3Digest2();
			this.sm3c3 = new SM3Digest2();
			var C = this.p2.getX().toBigInteger().toRadix(16);
			var D = this.p2.getY().toBigInteger().toRadix(16);
			if (C.length != 64) {
					for (var A = 64 - C.length,
					F = 0; F < A; F++) {
							C = "0" + C
					}
			}
			if (D.length != 64 && D.length != 64) {
					A = 64 - D.length;
					for (F = 0; F < A; F++) {
							D = "0" + D
					}
			}
			var B = this.GetWords(C);
			var E = this.GetWords(D);
			this.sm3c3.BlockUpdate(B, 0, B.length);
			this.sm3keybase.BlockUpdate(B, 0, B.length);
			this.sm3keybase.BlockUpdate(E, 0, E.length);
			this.ct = 1;
			this.NextKey()
	},
	NextKey: function() {
			var A = new SM3Digest2(this.sm3keybase);
			A.Update(this.ct >> 24 & 255);
			A.Update(this.ct >> 16 & 255);
			A.Update(this.ct >> 8 & 255);
			A.Update(this.ct & 255);
			A.DoFinal(this.key, 0);
			this.keyOff = 0;
			this.ct++
	},
	InitEncipher: function(A) {
			var F = null;
			var E = null;
			var D = new KJUR.crypto.ECDSA({
					"curve": "sm2"
			});
			var B = D.generateKeyPairHex();
			F = new BigInteger(B.ecprvhex, 16);
			var C = B.ecpubhex;
			E = ECPointFp.decodeFromHex(D.ecparams["curve"], C);
			this.p2 = A.multiply(F);
			this.Reset();
			return E
	},
	EncryptBlock: function(B) {
			this.sm3c3.BlockUpdate(B, 0, B.length);
			for (var A = 0; A < B.length; A++) {
					if (this.keyOff == this.key.length) {
							this.NextKey()
					}
					B[A] ^= this.key[this.keyOff++]
			}
	},
	InitDecipher: function(A, B) {
			this.p2 = B.multiply(A);
			this.Reset()
	},
	DecryptBlock: function(B) {
			for (var A = 0; A < B.length; A++) {
					if (this.keyOff == this.key.length) {
							this.NextKey()
					}
					B[A] ^= this.key[this.keyOff++]
			}
			this.sm3c3.BlockUpdate(B, 0, B.length)
	},
	Dofinal: function(B) {
			var C = this.p2.getY().toBigInteger().toRadix(16);
			if (C.length != 64 && C.length != 64) {
					var A = 64 - C.length;
					for (c = 0; c < A; c++) {
							C = "0" + C
					}
			}
			var D = this.GetWords(C);
			this.sm3c3.BlockUpdate(D, 0, D.length);
			this.sm3c3.DoFinal(B, 0);
			this.Reset()
	},
	Encrypt: function(G, E) {
			var B = new Array(E.length);
			Array.Copy(E, 0, B, 0, E.length);
			var A = this.InitEncipher(G);
			this.EncryptBlock(B);
			var F = new Array(32);
			this.Dofinal(F);
			var I;
			var D = A.getX().toBigInteger().toRadix(16);
			var C = A.getY().toBigInteger().toRadix(16);
			if (D.length != 64) {
					for (var J = 64 - D.length,
					H = 0; H < J; H++) {
							D = "0" + D
					}
			}
			if (C.length != 64 && C.length != 64) {
					J = 64 - C.length;
					for (H = 0; H < J; H++) {
							C = "0" + C
					}
			}
			switch (this.cipherMode) {
			case SM2CipherMode.C1C3C2:
					I = D + C + this.GetHex(F).toString() + this.GetHex(B).toString();
					break;
			case SM2CipherMode.C1C2C3:
					I = A.getX().toBigInteger().toRadix(16) + A.getY().toBigInteger().toRadix(16) + this.GetHex(B).toString() + this.GetHex(F).toString();
					break;
			default:
					throw new Error("[SM2:Decrypt]invalid type cipherMode(" + this.cipherMode + ")")
			}
			return I
	},
	GetWords: function(C) {
			var A = [];
			var D = C.length;
			for (var B = 0; B < D; B += 2) {
					A[A.length] = parseInt(C.substr(B, 2), 16)
			}
			return A
	},
	GetHex: function(D) {
			var A = new Array(32);
			var E = 0;
			for (var B = 0; B < D.length * 2; B += 2) {
					A[B >>> 3] |= parseInt(D[E]) << (24 - (B % 8) * 4);
					E++
			}
			var C = new CryptoJS.lib.WordArray.init(A, D.length);
			return C
	},
	Decrypt: function(O, N) {
			var I = N;
			var H = I.substr(0, 64);
			var G = I.substr(0 + H.length, 64);
			var B;
			var D;
			var L = new KJUR.crypto.ECDSA({
					"curve": "sm2"
			});
			var F = L.ecparams["n"];
			if (O.compareTo(F.subtract(BigInteger.ONE)) > 0) {
					return undefined
			}
			if (O.compareTo(BigInteger.ONE) < 0) {
					return undefined
			}
			switch (this.cipherMode) {
			case SM2CipherMode.C1C3C2:
					D = I.substr(H.length + G.length, 64);
					encrypData = I.substr(H.length + G.length + 64);
					break;
			case SM2CipherMode.C1C2C3:
					encrypData = I.substr(H.length + G.length, I.length - H.length - G.length - 64);
					D = I.substr(I.length - 64);
					break;
			default:
					throw new Error("[SM2:Decrypt]invalid type cipherMode(" + this.cipherMode + ")")
			}
			var E = this.GetWords(encrypData);
			var M = this.CreatePoint(H, G);
			if (M == undefined) {
					return undefined
			}
			this.InitDecipher(O, M);
			this.DecryptBlock(E);
			var K = new Array(32);
			this.Dofinal(K);
			var C = ((this.GetHex(K).toString().toLowerCase()) == (D.toLowerCase()));
			if (C) {
					var J = this.GetHex(E);
					var A = CryptoJS.enc.Utf8.stringify(J);
					return A
			} else {
					throw new Error("[SM2:Decrypt] C3 is not match!");
					return ""
			}
	},
	CreatePoint: function(D, E) {
			var F = new KJUR.crypto.ECDSA({
					"curve": "sm2"
			});
			var C = F.ecparams["curve"];
			var A = "04" + D + E;
			var B = ECPointFp.decodeFromHex(F.ecparams["curve"], A);
			if (B.isOnCurve() == 0) {
					return undefined
			}
			return B
	}
};
if (typeof KJUR == "undefined" || !KJUR) {
	KJUR = {}
}
if (typeof KJUR.crypto == "undefined" || !KJUR.crypto) {
	KJUR.crypto = {}
}
if (typeof KJUR == "undefined" || !KJUR) {
	KJUR = {}
}
if (typeof KJUR.crypto == "undefined" || !KJUR.crypto) {
	KJUR.crypto = {}
}
if (typeof KJUR == "undefined" || !KJUR) {
	KJUR = {}
}
if (typeof KJUR.crypto == "undefined" || !KJUR.crypto) {
	KJUR.crypto = {}
}
KJUR.crypto.ECDSA = function(C) {
	var D = "secp256r1";
	var E = null;
	var G = null;
	var A = null;
	var H = new SecureRandom();
	var F = null;
	this.type = "EC";
	this.getBigRandom = function(I) {
			return new BigInteger(I.bitLength(), H).mod(I.subtract(BigInteger.ONE)).add(BigInteger.ONE)
	};
	this.setNamedCurve = function(I) {
			this.ecparams = KJUR.crypto.ECParameterDB.getByName(I);
			this.prvKeyHex = null;
			this.pubKeyHex = null;
			this.curveName = I
	};
	this.setPrivateKeyHex = function(I) {
			this.isPrivate = true;
			this.prvKeyHex = I
	};
	this.setPublicKeyHex = function(I) {
			this.isPublic = true;
			this.pubKeyHex = I
	};
	this.generateKeyPairHex = function() {
			var L = this.ecparams["n"];
			var R = this.getBigRandom(L);
			var Q = this.ecparams["G"].multiply(R);
			var M = Q.getX().toBigInteger();
			var N = Q.getY().toBigInteger();
			var J = this.ecparams["keylen"] / 4;
			var O = ("0000000000" + R.toString(16)).slice( - J);
			var I = ("0000000000" + M.toString(16)).slice( - J);
			var P = ("0000000000" + N.toString(16)).slice( - J);
			var K = "04" + I + P;
			this.setPrivateKeyHex(O);
			this.setPublicKeyHex(K);
			return {
					"ecprvhex": O,
					"ecpubhex": K
			}
	};
	if (C !== undefined) {
			if (C["curve"] !== undefined) {
					this.curveName = C["curve"]
			}
	}
	if (this.curveName === undefined) {
			this.curveName = D
	}
	this.setNamedCurve(this.curveName);
	if (C !== undefined) {
			if (C["prv"] !== undefined) {
					this.setPrivateKeyHex(C["prv"])
			}
			if (C["pub"] !== undefined) {
					this.setPublicKeyHex(C["pub"])
			}
	}
};
KJUR.crypto.ECParameterDB = new
function() {
	var B = {};
	var C = {};
	function A(D) {
			return new BigInteger(D, 16)
	}
	this.getByName = function(D) {
			var E = D;
			if (typeof C[E] != "undefined") {
					E = C[D]
			}
			if (typeof B[E] != "undefined") {
					return B[E]
			}
			throw "unregistered EC curve name: " + E
	};
	this.regist = function(R, X, Q, K, T, U, I, V, O, W, F, D) {
			B[R] = {};
			var E = A(Q);
			var M = A(K);
			var L = A(T);
			var J = A(U);
			var H = A(I);
			var P = new ECCurveFp(E, M, L);
			var S = P.decodePointHex("04" + V + O);
			B[R]["name"] = R;
			B[R]["keylen"] = X;
			B[R]["curve"] = P;
			B[R]["G"] = S;
			B[R]["n"] = J;
			B[R]["h"] = H;
			B[R]["oid"] = F;
			B[R]["info"] = D;
			for (var N = 0; N < W.length; N += 1) {
					C[W[N]] = R
			}
	}
};
KJUR.crypto.ECParameterDB.regist("secp128r1", 128, "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF", "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFC", "E87579C11079F43DD824993C2CEE5ED3", "FFFFFFFE0000000075A30D1B9038A115", "1", "161FF7528B899B2D0C28607CA52C5B86", "CF5AC8395BAFEB13C02DA292DDED7A83", [], "", "secp128r1 : SECG curve over a 128 bit prime field");
KJUR.crypto.ECParameterDB.regist("secp160k1", 160, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73", "0", "7", "0100000000000000000001B8FA16DFAB9ACA16B6B3", "1", "3B4C382CE37AA192A4019E763036F4F5DD4D7EBB", "938CF935318FDCED6BC28286531733C3F03C4FEE", [], "", "secp160k1 : SECG curve over a 160 bit prime field");
KJUR.crypto.ECParameterDB.regist("secp160r1", 160, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF", "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC", "1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45", "0100000000000000000001F4C8F927AED3CA752257", "1", "4A96B5688EF573284664698968C38BB913CBFC82", "23A628553168947D59DCC912042351377AC5FB32", [], "", "secp160r1 : SECG curve over a 160 bit prime field");
KJUR.crypto.ECParameterDB.regist("secp192k1", 192, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFEE37", "0", "3", "FFFFFFFFFFFFFFFFFFFFFFFE26F2FC170F69466A74DEFD8D", "1", "DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D", "9B2F2F6D9C5628A7844163D015BE86344082AA88D95E2F9D", []);
KJUR.crypto.ECParameterDB.regist("secp192r1", 192, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF", "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC", "64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1", "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831", "1", "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012", "07192B95FFC8DA78631011ED6B24CDD573F977A11E794811", []);
KJUR.crypto.ECParameterDB.regist("secp224r1", 224, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001", "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE", "B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4", "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D", "1", "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21", "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34", []);
KJUR.crypto.ECParameterDB.regist("secp256k1", 256, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", "0", "7", "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", "1", "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798", "483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8", []);
KJUR.crypto.ECParameterDB.regist("secp256r1", 256, "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF", "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC", "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B", "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551", "1", "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296", "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5", ["NIST P-256", "P-256", "prime256v1"]);
KJUR.crypto.ECParameterDB.regist("secp384r1", 384, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF", "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC", "B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF", "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973", "1", "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7", "3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f", ["NIST P-384", "P-384"]);
KJUR.crypto.ECParameterDB.regist("secp521r1", 521, "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC", "051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00", "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409", "1", "C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66", "011839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650", ["NIST P-521", "P-521"]);
KJUR.crypto.ECParameterDB.regist("sm2", 256, "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF", "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC", "28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93", "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123", "1", "32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7", "BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0", ["sm2", "SM2"]);

function SM2() {
	this.ecc_p = new BigInteger(sm2_ecParams['p'], 16);
	this.ecc_a = new BigInteger(sm2_ecParams['a'], 16);
	this.ecc_b = new BigInteger(sm2_ecParams['b'], 16);
	this.ecc_n = new BigInteger(sm2_ecParams['n'], 16);
	this.ecc_gx = new BigInteger(sm2_ecParams['gx'], 16);
	this.ecc_gy = new BigInteger(sm2_ecParams['gy'], 16);
	this.rng = new SecureRandom();

	this.ecCurve = new ECCurveFp(this.ecc_p, this.ecc_a, this.ecc_b);
	this.ecPointG = ECPointFp.decodeFromHex(this.ecCurve, "04" + sm2_ecParams['gx'] + sm2_ecParams['gy']);
	if (debug == true) {
		console.log("ax1=" + this.ecCurve.getA().toBigInteger().toString(16));
		console.log("by1=" + this.ecCurve.getB().toBigInteger().toString(16));
		console.log("gx1=" + this.ecPointG.getX().toBigInteger().toString(16));
		console.log("gy1=" + this.ecPointG.getY().toBigInteger().toString(16));
	}
}
window.SM2CipherMode = {
	C1C2C3: 0,
	C1C3C2: 1
};
SM2.prototype = {
	generateKeyPairHex: function () {
		var A = new KJUR.crypto.ECDSA({
			"curve": "SM2"
		}).generateKeyPairHex();
		return {
			pubkeyhex:A.ecpubhex,
			privkeyhex:A.ecprvhex
		}
	},
	encrypt: function (C, D) {
		if (D == undefined || C == undefined) {
			return undefined
		}
		if (D == "" || C == "") {
				return undefined
		}
		if (C.length != 130) {
				return undefined
		}
		var E = CryptoJS.enc.Utf8.parse(D);
		var J = C;
    var I = J.substr(0, 2);
		if (I != "04") {
			return undefined
		}
		if (J.length > 64 * 2) {
			J = J.substr(J.length - 64 * 2)
		}
		var B = J.substr(0, 64);
    var F = J.substr(64);
		var A = new SM2Cipher(1);
		var H = A.CreatePoint(B, F);
		if (H == undefined) {
			return undefined
		}
		E = A.GetWords(E.toString());
    var G = A.Encrypt(H, E);
		var result = "04" + G
    return result.toUpperCase()
	},
	decrypt: function (D, B) {
		if (B == undefined || D == undefined) {
			return undefined
		}
		if (B == "" || D == "") {
				return undefined
		}
		if (D.length != 64) {
				return undefined
		}
		if (B.length <= 194) {
				return undefined
		}
		var F = B.substr(0, 2);
		if (F != "04") {
				return undefined
		}
		B = B.substr(2);
		var E = new BigInteger(D, 16);
    var C = new SM2Cipher(1);
    var A = C.Decrypt(E, B);
    return A
	},
}